Passed
Push — master ( 0e29a7...dfba81 )
by Mathieu
02:20 queued 23s
created

DateUtilsAdapter.getLastDayOfYear   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
import { Injectable } from '@nestjs/common';
2
import {
3
  format as fnsFormat,
4
  isWeekend as fnsIsWeekend,
5
  getDaysInMonth as fnsGetDaysInMonth,
6
  eachDayOfInterval,
7
  addDays,
8
  getYear
9
} from 'date-fns';
10
import { IDateUtils } from 'src/Application/IDateUtils';
11
12
@Injectable()
13
export class DateUtilsAdapter implements IDateUtils {
14
  public format(date: Date, format: string): string {
15
    return fnsFormat(date, format);
16
  }
17
18
  public getDaysInMonth(date: Date): number {
19
    return fnsGetDaysInMonth(date);
20
  }
21
22
  public isWeekend(date: Date): boolean {
23
    return fnsIsWeekend(date);
24
  }
25
26
  public isAWorkingDay(date: Date): boolean {
27
    if (this.isWeekend(date)) {
28
      return false;
29
    }
30
31
    const workedFreeDays = this.getWorkedFreeDays(date.getFullYear());
32
    const formatedDate = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
33
34
    for (const day of workedFreeDays) {
35
      const formatedDay = `${day.getFullYear()}-${day.getMonth()}-${day.getDate()}`;
36
37
      if (formatedDate === formatedDay) {
38
        return false;
39
      }
40
    }
41
42
    return true;
43
  }
44
45
  public getCurrentDate(): Date {
46
    return new Date();
47
  }
48
49
  public getYear(date: Date): number {
50
    return getYear(date);
51
  }
52
53
  public getLastDayOfYear(date: Date): Date {
54
    return new Date(`${getYear(date)}/12/31`);
55
  }
56
57
  public getFirstDayOfYear(date: Date): Date {
58
    return new Date(`${getYear(date)}/01/01`);
59
  }
60
61
  public getCurrentDateToISOString(): string {
62
    return this.getCurrentDate().toISOString();
63
  }
64
65
  public addDaysToDate(date: Date, days: number): Date {
66
    return addDays(date, days);
67
  }
68
69
  public getWorkedDaysDuringAPeriod(start: Date, end: Date): Date[] {
70
    const dates: Date[] = [];
71
    const workedFreeDays: Date[] = [];
72
73
    for (let year = start.getFullYear(); year <= end.getFullYear(); year++) {
74
      workedFreeDays.push(...this.getWorkedFreeDays(year));
75
    }
76
77
    for (const day of eachDayOfInterval({ start, end })) {
78
      if (
79
        this.isWeekend(day) ||
80
        workedFreeDays.filter(d => d.toISOString() === day.toISOString())
81
          .length > 0
82
      ) {
83
        continue;
84
      }
85
86
      dates.push(day);
87
    }
88
89
    return dates;
90
  }
91
92
  public getWorkedFreeDays(year: number): Date[] {
93
    const fixedDays: Date[] = [
94
      new Date(`${year}-01-01`), // New Year's Day
95
      new Date(`${year}-05-01`), // Labour Day
96
      new Date(`${year}-05-08`), // Victory in 1945
97
      new Date(`${year}-07-14`), // National Day
98
      new Date(`${year}-08-15`), // Assumption
99
      new Date(`${year}-11-01`), // All Saints' Day
100
      new Date(`${year}-11-11`), // The Armistice
101
      new Date(`${year}-12-25`) // Christmas
102
    ];
103
104
    const easterDate = this.getEasterDate(year);
105
    const easterDays: Date[] = [
106
      addDays(easterDate, 1), // Easter Monday
107
      addDays(easterDate, 39) // Ascension
108
    ];
109
110
    return [...fixedDays, ...easterDays];
111
  }
112
113
  public getEasterDate(year: number): Date {
114
    const a = year % 19;
115
    const b = Math.floor(year / 100);
116
    const c = year % 100;
117
    const d = Math.floor(b / 4);
118
    const e = b % 4;
119
    const f = Math.floor((b + 8) / 25);
120
    const g = Math.floor((b - f + 1) / 3);
121
    const h = (19 * a + b - d - g + 15) % 30;
122
    const i = Math.floor(c / 4);
123
    const k = c % 4;
124
    const l = (32 + 2 * e + 2 * i - h - k) % 7;
125
    const m = Math.floor((a + 11 * h + 22 * l) / 451);
126
    const n0 = h + l + 7 * m + 114;
127
    const n = Math.floor(n0 / 31) - 1;
128
    const p = (n0 % 31) + 1;
129
130
    return new Date(year, n, p);
131
  }
132
133
  public getLeaveDuration(
134
    startDate: string,
135
    isStartsAllDay: boolean,
136
    endDate: string,
137
    isEndsAllDay: boolean
138
  ): number {
139
    let duration = this.getWorkedDaysDuringAPeriod(
140
      new Date(startDate),
141
      new Date(endDate)
142
    ).length;
143
144
    if (false === isStartsAllDay) {
145
      duration -= 0.5;
146
    }
147
148
    if (false === isEndsAllDay && duration > 0.5) {
149
      duration -= 0.5;
150
    }
151
152
    return duration;
153
  }
154
}
155